package com.tal.bcc.pad.cloud.utils;

import com.tal.bcc.pad.cloud.Log;
import org.apache.http.util.TextUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Locale;
import java.util.regex.Pattern;


/**
 * 参数校验类
 *
 * @author houbs
 */
public class XesCheckUtils {

    /**
     * 验证邮箱地址是否正确
     *
     * @param email
     * @return
     */
    public static boolean isEmail(String email) {
        if (email == null || email.trim().length() == 0)
            return false;
        String pattern = "[_\\w\\-]+(\\.[_\\w\\-]*)*@[\\w\\-]+\\.[a-z]+(\\.[a-z]+)?";
        return Pattern.compile(pattern).matcher(email).matches();
    }

    /**
     * 校验金额大小
     *
     * @param amount
     * @return
     */
    public static boolean isAmount(BigDecimal amount) {
        if (amount == null || amount.compareTo(new BigDecimal("0.01")) < 1
                || amount.compareTo(new BigDecimal("99999999999999.99")) >= 0) {
            return false;
        }
        return true;
    }

    /**
     * 验证手机号码
     *
     * @param mobile
     * @return
     */
    public static boolean isMobile(String mobile) {
        if (TextUtils.isEmpty(mobile)) {
            return false;
        }
        Pattern phonner = Pattern.compile("[0-9]{11}");
        return phonner.matcher(mobile).matches();
    }

    /**
     * 校验是否符合账户名
     *
     * @param accout
     * @return
     */
    public static boolean isAccount(String accout) {
        if (isMobile(accout) || isEmail(accout)) {
            return true;
        }
        return false;
    }

    /**
     * 验证身份证
     *
     * @return true：合法， false：不合法
     * @author xingtongju
     * 身份证号码
     */
    public static boolean isID(String ID) {
        if (ID == null || ID.trim().length() == 0)
            return false;
        String regx1 = "[0-9]{17}x";
        String regx2 = "[0-9]{17}X";
        String regx3 = "[0-9]{15}";
        String rege4 = "[0-9]{18}";
        return (ID.matches(regx1) || ID.matches(regx2) || ID.matches(regx3) || ID
                .matches(rege4));
    }

    /**
     * 校验银行卡卡号
     *
     * @param bankCard
     * @return
     */
    public static boolean isBankCard(String bankCard) {
        if (TextUtils.isEmpty(bankCard))
            return false;
        String cardId = bankCard.trim();
        String reg1 = "[0-9]{14,19}";
        if (cardId.matches(reg1)) {
            return true;
        }
        return false;
    }

    /**
     * 从不含校验位的银行卡卡号采用 Luhm 校验算法获得校验位
     *
     * @param nonCheckCodeCardId
     * @return
     */
    public static char getBankCardCheckCode(String nonCheckCodeCardId) {
        if (nonCheckCodeCardId == null
                || nonCheckCodeCardId.trim().length() == 0
                || !nonCheckCodeCardId.matches("\\d+")) {
            // 如果传的不是数据返回N
            return 'N';
        }
        char[] chs = nonCheckCodeCardId.trim().toCharArray();
        int luhmSum = 0;
        for (int i = chs.length - 1, j = 0; i >= 0; i--, j++) {
            int k = chs[i] - '0';
            if (j % 2 == 0) {
                k *= 2;
                k = k / 10 + k % 10;
            }
            luhmSum += k;
        }
        return (luhmSum % 10 == 0) ? '0' : (char) ((10 - luhmSum % 10) + '0');
    }

    /**
     * 检测短信验证码格式
     *
     * @param checkcode
     * @return 合法：true
     */
    public static boolean isSMSCheckCode(String checkcode) {
        if (TextUtils.isEmpty(checkcode)) {
            return false;
        }
        String regex = "[A-Za-z0-9]{6}";
        return (checkcode.matches(regex));
    }

    /**
     * 校验密码格式
     *
     * @param password
     * @return
     */
    public static boolean isPassword(String password) {
        return isPassword(password, false);
    }

    /**
     * 校验密码格式
     *
     * @param password
     * @param strict   严格校验
     * @return
     */
    public static boolean isPassword(String password, boolean strict) {
        if (password == null) {
            return false;
        }
        password = password.trim();
        boolean result = false;
        try {
            // 位数和非空
            String regLen = "^.{6,20}$";
            String regSpace = "[\\s]";
            result = Pattern.compile(regLen).matcher(password).find()
                    && !Pattern.compile(regSpace).matcher(password).find();
            if (!result) {
                return false;
            }
            if (!strict) {
                return result;
            }
            // 严格限定
            int matchCount = 0;
            // 数字
            String reg1 = "[0-9]";
            if (Pattern.compile(reg1).matcher(password).find()) {
                matchCount++;
            }
            // 小写字母
            String reg2 = "[a-z]";
            if (Pattern.compile(reg2).matcher(password).find()) {
                matchCount++;
            }
            // 大写字母
            String reg3 = "[A-Z]";
            if (Pattern.compile(reg3).matcher(password).find()) {
                matchCount++;
            }
            // 字符
            String reg4 = "[^0-9a-zA-Z]";
            if (Pattern.compile(reg4).matcher(password).find()) {
                matchCount++;
            }
            result = matchCount >= 2;
        } catch (Exception e) {
            result = false;
        }
        return result;
    }

    /**
     * 判断是否是cvv
     *
     * @param cvv
     * @return
     */
    public static boolean isCVV(String cvv) {
        if (TextUtils.isEmpty(cvv) || !isNumeric(cvv) || cvv.length() != 3) {
            return false;
        }
        return true;
    }

    /**
     * 校验信用卡有效期
     *
     * @param validDate
     * @return
     */
    public static boolean isValidDate(String validDate) {
        if (validDate == null) {
            return false;
        }
        validDate = validDate.trim();
        // 数字
        String reg1 = "(0[1-9]|1[0-2])/[0-9]{2}";
        return Pattern.compile(reg1).matcher(validDate).find();
    }

    /**
     * 验证URL地址
     *
     * @param url 格式：http://blog.csdn.net:80/xyang81/article/details/7705960? 或
     *            http://www.csdn.net:80
     * @return 验证成功返回true，验证失败返回false
     */
    public static boolean isURL(String url) {
        String http = "http://";
        String https = "https://";
        if (TextUtils.isEmpty(url)) {
            return false;
        }
        return url.startsWith(http) || url.startsWith(https);
    }

    /**
     * 是否为汉字
     *
     * @param c
     * @return
     */
    public static boolean isChinese(char c) {
        if ((int) c == 65292) {
            return false;
        }
        if ((19968 <= (int) c) && ((int) c <= 171941)) {
            return true;
        }
        return false;
    }

    /**
     * 判断是否为英文
     *
     * @param c
     * @return
     */
    public static boolean isABC(char c) {
        if (!(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z')) {
            return false;
        }
        return true;
    }

    /**
     * 判断是否为数字
     *
     * @param str
     * @return
     */
    public static boolean isNumeric(String str) {
        Pattern pattern = Pattern.compile("[0-9]*");
        return pattern.matcher(str).matches();
    }

    /**
     * 判断是否为表情
     *
     * @param c
     * @return
     */
    public static boolean isFace(char c) {
        if ((int) c == 55357) {
            return true;
        }
        return false;
    }

    /**
     * 判断是否为实名，实名需中文或英文，2-18位
     *
     * @param name
     * @return
     */
    public static boolean isName(String name) {
        int length = name.length();
        // 如果长度错误则返回失败
        if (length < 2 || length > 18) {
            return false;
        }
        return true;
    }

    /**
     * 判断是否为实名，实名需中文或英文，2-18位
     *
     * @param c
     * @return
     */
    public static boolean isName(char c) {
        if (isChinese(c) || isABC(c) || c == ' ' || c == '.' || c == '*') {
            return true;
        }
        return false;
    }

    /**
     * 判断字符串是否是数字
     * @param str
     * @return
     */
    public static boolean isInteger(String str) {
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
        return pattern.matcher(str).matches();
    }

    public static final String CPU_ARCHITECTURE_TYPE_32 = "32";
    public static final String CPU_ARCHITECTURE_TYPE_64 = "64";

    /** ELF文件头 e_indent[]数组文件类标识索引 */
    private static final int EI_CLASS = 4;
    /** ELF文件头 e_indent[EI_CLASS]的取值：ELFCLASS32表示32位目标 */
    private static final int ELFCLASS32 = 1;
    /** ELF文件头 e_indent[EI_CLASS]的取值：ELFCLASS64表示64位目标 */
    private static final int ELFCLASS64 = 2;

    /** The system property key of CPU arch type */
    private static final String CPU_ARCHITECTURE_KEY_64 = "ro.product.cpu.abilist64";

    /** The system libc.so file path */
    private static final String SYSTEM_LIB_C_PATH = "/system/lib/libc.so";
    private static final String SYSTEM_LIB_C_PATH_64 = "/system/lib64/libc.so";
    private static final String PROC_CPU_INFO_PATH = "/proc/cpuinfo";

    private static boolean LOGENABLE = false;


    /**
     * Get the CPU arch type: x32 or x64
     */
    public static String getArchType() {
        if (getSystemProperty(CPU_ARCHITECTURE_KEY_64, "").length() > 0) {
            if (LOGENABLE) {
                Log.d("getSystemProperty","CPU arch is 64bit");
            }
            return CPU_ARCHITECTURE_TYPE_64;
        } else if (isCPUInfo64()) {
            return CPU_ARCHITECTURE_TYPE_64;
        } else if (isLibc64()) {
            return CPU_ARCHITECTURE_TYPE_64;
        } else {
            if (LOGENABLE) {
                Log.d("getArchType()","return cpu DEFAULT 32bit!");
            }
            return CPU_ARCHITECTURE_TYPE_32;
        }
    }

    private static String getSystemProperty(String key, String defaultValue) {
        String value = defaultValue;
        try {
            Class<?> clazz= Class.forName("android.os.SystemProperties");
            Method get = clazz.getMethod("get", String.class, String.class);
            value = (String)(get.invoke(clazz, key, ""));
        } catch (Exception e) {
            if (LOGENABLE) {
                Log.d("getSystemProperty", "key = " + key + ", error = " + e.getMessage());
            }
        }

        if (LOGENABLE) {
            Log.d("getSystemProperty",  key + " = " + value);
        }
        return value;
    }

    /**
     * Read the first line of "/proc/cpuinfo" file, and check if it is 64 bit.
     */
    private static boolean isCPUInfo64() {
        File cpuInfo = new File(PROC_CPU_INFO_PATH);
        if (cpuInfo != null && cpuInfo.exists()) {
            InputStream inputStream = null;
            BufferedReader bufferedReader = null;
            try {
                inputStream = new FileInputStream(cpuInfo);
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream), 512);
                String line = bufferedReader.readLine();
                if (line != null && line.length() > 0 && line.toLowerCase(Locale.US).contains("arch64")) {
                    if (LOGENABLE) {
                        Log.d("isCPUInfo64()", PROC_CPU_INFO_PATH + " contains is arch64");
                    }
                    return true;
                } else {
                    if (LOGENABLE) {
                        Log.d("isCPUInfo64()", PROC_CPU_INFO_PATH + " is not arch64");
                    }
                }
            } catch (Throwable t) {
                if (LOGENABLE) {
                    Log.d("isCPUInfo64()","read " + PROC_CPU_INFO_PATH + " error = " + t.toString());
                }
            } finally {
                try {
                    if (bufferedReader != null) {
                        bufferedReader.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

                try {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return false;
    }

    /**
     * Check if system libc.so is 32 bit or 64 bit
     */
    private static boolean isLibc64() {
        File libcFile = new File(SYSTEM_LIB_C_PATH);
        if (libcFile != null && libcFile.exists()) {
            byte[] header = readELFHeadrIndentArray(libcFile);
            if (header != null && header[EI_CLASS] == ELFCLASS64) {
                if (LOGENABLE) {
                    Log.d("isLibc64()", SYSTEM_LIB_C_PATH + " is 64bit");
                }
                return true;
            }
        }

        File libcFile64 = new File(SYSTEM_LIB_C_PATH_64);
        if (libcFile64 != null && libcFile64.exists()) {
            byte[] header = readELFHeadrIndentArray(libcFile64);
            if (header != null && header[EI_CLASS] == ELFCLASS64) {
                if (LOGENABLE) {
                    Log.d("isLibc64()", SYSTEM_LIB_C_PATH_64 + " is 64bit");
                }
                return true;
            }
        }

        return false;
    }

    /**
     * ELF文件头格式是固定的:文件开始是一个16字节的byte数组e_indent[16]
     * e_indent[4]的值可以判断ELF是32位还是64位
     */
    private static byte[] readELFHeadrIndentArray(File libFile) {
        if (libFile != null && libFile.exists()) {
            FileInputStream inputStream = null;
            try {
                inputStream = new FileInputStream(libFile);
                if (inputStream != null) {
                    byte[] tempBuffer = new byte[16];
                    int count = inputStream.read(tempBuffer, 0, 16);
                    if (count == 16) {
                        return tempBuffer;
                    } else {
                        if (LOGENABLE) {
                            Log.e("readELFHeadrIndentArray", "Error: e_indent lenght should be 16, but actual is " + count);
                        }
                    }
                }
            } catch (Throwable t) {
                if (LOGENABLE) {
                    Log.e("readELFHeadrIndentArray", "Error:" + t.toString());
                }
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        return null;
    }
    
}